Building REST APIs and Understanding JSON-Based Communication
Course: Python Training
Topic: Building REST APIs and Understanding JSON-Based Communication
Course Link: Python Training Course
Demo Link: Register for a Course Demo
Website: JustAcademy Official Website
1. Introduction to REST APIs and JSON Communication
REST APIs and JSON-based communication are fundamental concepts in modern Python web development. They allow different applications, services, and devices to exchange information over a network using standardized HTTP requests and responses.
A REST API enables a client application to interact with resources managed by a server. For example, a mobile application can request product information from an online store, submit login credentials to an authentication service, or retrieve student records from a learning platform.
JSON (JavaScript Object Notation) is a lightweight data format commonly used to exchange information between clients and servers. Python applications can convert dictionaries, lists, and other supported data into JSON and process JSON received from other applications.
Learning Objectives
- Understand APIs, REST architecture, and RESTful services.
- Learn the HTTP methods used in API development.
- Understand JSON syntax, data types, and structures.
- Build REST API endpoints using Flask.
- Receive JSON request bodies and return JSON responses.
- Implement CRUD operations for resources.
- Use appropriate HTTP status codes and error responses.
- Validate incoming data and handle API exceptions.
- Test APIs using Postman, curl, and Python Requests.
- Understand authentication, security, and API best practices.
2. What Is an API?
API stands for Application Programming Interface. It defines how one software application can interact with another through a documented set of operations, inputs, and outputs.
An API acts as an interface between systems. A client does not need to know the internal implementation of the server; it only needs to understand the available endpoints, required parameters, authentication requirements, and response formats.
Example of an API in Real Life
Consider an online shopping application. When a user opens a product page, the application may request product information from a backend API. The server retrieves the product data and returns it to the client, often in JSON format.
Client Application
|
| GET /api/products/101
v
Python REST API
|
| Retrieve product information
v
Database
|
| Product record
v
Python REST API
|
| JSON Response
v
Client Application
Common Types of APIs
| API Type |
Description |
Example |
| REST API |
Uses HTTP methods and resource-oriented URLs. |
Product management API. |
| SOAP API |
Uses a structured messaging protocol commonly based on XML. |
Some enterprise integrations. |
| GraphQL API |
Allows clients to request specific fields through a query language. |
Applications that need flexible data retrieval. |
| WebSocket API |
Supports persistent, bidirectional communication. |
Live chat and real-time notifications. |
3. What Is a REST API?
REST stands for Representational State Transfer. It is an architectural style for designing networked applications. A REST API exposes resources through URLs and commonly uses HTTP methods to retrieve, create, update, and delete those resources.
For example, a student management API might expose endpoints such as:
GET /api/students
GET /api/students/10
POST /api/students
PUT /api/students/10
PATCH /api/students/10
DELETE /api/students/10
These endpoints represent a collection of students and an individual student identified by an ID.
Key Characteristics of REST
- Resource-oriented: URLs identify resources such as students, products, and orders.
- Client-server separation: The client interface and server-side business logic can be developed independently.
- Stateless communication: Each request contains the information needed to process it; the server does not rely on stored client session state to understand the request.
- Uniform interface: Resources are accessed through consistent interaction rules.
- Cacheability: Responses can be cached when appropriate HTTP caching rules allow it.
- Layered architecture: Clients may communicate through intermediaries such as proxies and gateways.
REST is an architectural style, not a specific Python library or protocol. JSON is a common representation used by REST APIs, but REST does not require JSON in every implementation.
4. Understanding HTTP Communication
HTTP (Hypertext Transfer Protocol) is the communication protocol commonly used by REST APIs. A client sends an HTTP request to a server, and the server returns an HTTP response.
Structure of an HTTP Request
- Method: Specifies the requested operation, such as GET or POST.
- URL: Identifies the endpoint or resource.
- Headers: Provide metadata such as content type and authorization.
- Query parameters: Supply optional filtering, searching, or pagination information.
- Request body: Contains data sent to the server, commonly for POST, PUT, or PATCH requests.
Example HTTP Request
POST /api/students HTTP/1.1
Host: example.com
Content-Type: application/json
Accept: application/json
{
"name": "Aarav Sharma",
"email": "[email protected]",
"course": "Python"
}
Structure of an HTTP Response
- Status code: Indicates the result of the request.
- Headers: Describe the response, including its content type.
- Response body: Contains the requested data, confirmation, or error details.
Example HTTP Response
HTTP/1.1 201 Created
Content-Type: application/json
{
"id": 101,
"name": "Aarav Sharma",
"email": "[email protected]",
"course": "Python"
}
The server has successfully created a student resource and returned its identifier.
5. HTTP Methods Used in REST APIs
HTTP methods define the action a client wants to perform on a resource.
| Method |
Purpose |
Example |
| GET |
Retrieve a resource or collection. |
Get all students. |
| POST |
Create a resource or submit data for processing. |
Create a student. |
| PUT |
Replace the representation of a resource. |
Replace student details. |
| PATCH |
Partially update a resource. |
Change a student's email. |
| DELETE |
Delete a resource. |
Remove a student. |
GET Example
GET /api/products
This request retrieves a collection of products. GET requests should not be used to perform unintended changes to server data.
POST Example
POST /api/products
Content-Type: application/json
{
"name": "Wireless Mouse",
"price": 799
}
This request submits a new product representation to the server for creation.
PUT Versus PATCH
PUT generally replaces the target resource representation, while PATCH applies partial modifications. The precise behavior depends on the API contract. PUT is defined as an idempotent HTTP method, whereas PATCH is not necessarily idempotent.
6. What Is JSON?
JSON stands for JavaScript Object Notation. It is a text-based data interchange format that is easy for humans to read and easy for software to parse.
Although JSON originated from JavaScript object notation, it is language-independent and is widely supported by Python, Java, JavaScript, PHP, C#, Go, and other programming languages.
Basic JSON Example
{
"id": 101,
"name": "Aarav Sharma",
"age": 22,
"course": "Python",
"is_active": true
}
This JSON object represents a student with an identifier, name, age, course, and active status.
JSON Data Types
| JSON Type |
Example |
Description |
| String |
"name": "Aarav" |
Text enclosed in double quotation marks. |
| Number |
"age": 22 |
Integer or decimal number. |
| Boolean |
"active": true |
Either true or false. |
| Null |
"middle_name": null |
Represents the absence of a value. |
| Object |
{"city": "Mumbai"} |
A collection of key-value pairs. |
| Array |
["Python", "SQL"] |
An ordered collection of values. |
Important JSON Rules
- Object keys must be strings enclosed in double quotation marks.
- String values must use double quotation marks.
- JSON uses
true and false, not Python's True and False.
- JSON uses
null, not Python's None.
- Trailing commas are not allowed.
- JSON does not support comments.
- JSON objects use key-value pairs, while arrays use square brackets.
7. JSON Objects and Arrays
JSON objects and arrays are frequently used to represent API resources and collections.
JSON Object
{
"id": 1,
"name": "Priya",
"city": "Mumbai"
}
An object stores related values under named keys.
JSON Array
[
"Python",
"Flask",
"REST APIs",
"JSON"
]
An array stores an ordered sequence of values.
Array of Objects
[
{
"id": 1,
"name": "Priya",
"course": "Python"
},
{
"id": 2,
"name": "Rohan",
"course": "Django"
}
]
This structure is commonly used when an API returns multiple records, such as a list of students or products.
8. Working with JSON in Python
Python provides the built-in json module for converting Python objects to JSON text and parsing JSON text into Python objects.
Import the JSON Module
import json
Convert a Python Dictionary to JSON
import json
student = {
"id": 101,
"name": "Aarav",
"course": "Python",
"active": True
}
json_text = json.dumps(student, indent=4)
print(json_text)
The json.dumps() function serializes a Python object into a JSON-formatted string. The indent=4 argument makes the output easier to read.
Convert JSON Text to a Python Object
import json
json_text = '''
{
"name": "Aarav",
"age": 22,
"course": "Python"
}
'''
student = json.loads(json_text)
print(student["name"])
print(student["age"])
The json.loads() function parses JSON text and returns the corresponding Python object, such as a dictionary or list.
Read JSON from a File
import json
with open("student.json", "r", encoding="utf-8") as file:
student = json.load(file)
print(student)
Write JSON to a File
import json
student = {
"name": "Priya",
"course": "Python"
}
with open("student.json", "w", encoding="utf-8") as file:
json.dump(student, file, indent=4)
JSON Functions Summary
| Function |
Purpose |
json.dumps() |
Converts a Python object into a JSON string. |
json.loads() |
Parses a JSON string into a Python object. |
json.dump() |
Writes JSON data to a file-like object. |
json.load() |
Reads JSON data from a file-like object. |
9. Introduction to Flask for REST API Development
Flask is a lightweight Python web framework suitable for creating web applications and REST APIs. It provides routing, request handling, response generation, and JSON support.
Flask can automatically convert supported Python dictionaries and lists returned from a view into JSON responses. The jsonify() helper is also available when an explicit JSON response is useful.
Install Flask
python -m pip install flask
Create a Basic Flask Application
from flask import Flask
app = Flask(__name__)
@app.route("/")
def home():
return {"message": "Welcome to the REST API"}
if __name__ == "__main__":
app.run(debug=True)
Save the code as app.py and run it with python app.py. Open the local URL shown in the terminal and visit the root endpoint.
The root route returns a dictionary, which Flask converts into a JSON response. Debug mode should be used only in local development.
10. Creating a REST API with Flask
To build a REST API, define endpoints that represent resources and connect them to functions that process HTTP requests.
Example: A Simple Products API
from flask import Flask, jsonify
app = Flask(__name__)
products = [
{"id": 1, "name": "Keyboard", "price": 1200},
{"id": 2, "name": "Mouse", "price": 700},
{"id": 3, "name": "Monitor", "price": 9500}
]
@app.get("/api/products")
def get_products():
return jsonify(products)
if __name__ == "__main__":
app.run(debug=True)
When a client sends a GET request to /api/products, the API returns a JSON array containing the available products.
Example Response
[
{
"id": 1,
"name": "Keyboard",
"price": 1200
},
{
"id": 2,
"name": "Mouse",
"price": 700
},
{
"id": 3,
"name": "Monitor",
"price": 9500
}
]
11. Reading JSON Data from Requests
APIs often receive JSON data when a client creates or updates a resource. Flask provides request utilities to inspect the request content type and parse a JSON request body.
Example: Create a Product
from flask import Flask, request
app = Flask(__name__)
@app.post("/api/products")
def create_product():
if not request.is_json:
return {"error": "Content-Type must be application/json"}, 415
data = request.get_json()
if not isinstance(data, dict):
return {"error": "Expected a JSON object"}, 400
name = data.get("name")
price = data.get("price")
if not isinstance(name, str) or not name.strip():
return {"error": "Product name is required"}, 400
if isinstance(price, bool) or not isinstance(price, (int, float)):
return {"error": "Price must be a number"}, 400
if price < 0:
return {"error": "Price cannot be negative"}, 400
return {
"message": "Product data received",
"product": {
"name": name.strip(),
"price": price
}
}, 201
if __name__ == "__main__":
app.run(debug=True)
This example validates the JSON structure, checks required fields, and returns a suitable status code. It demonstrates receiving and validating product data; it does not persist the product in a database.
Example JSON Request Body
{
"name": "Mechanical Keyboard",
"price": 2499
}
The client should send the header Content-Type: application/json so that the server can interpret the request body correctly.
12. Understanding JSON Serialization and Deserialization
Serialization converts an in-memory object into a transferable representation. Deserialization converts that representation back into a usable object.
- Serialization: Python dictionary to JSON text.
- Deserialization: JSON text to Python dictionary.
Serialization Example
import json
product = {
"id": 101,
"name": "Headphones",
"price": 1499
}
serialized_data = json.dumps(product)
print(serialized_data)
Deserialization Example
import json
serialized_data = '{"id": 101, "name": "Headphones", "price": 1499}'
product = json.loads(serialized_data)
print(product["name"])
print(product["price"])
JSON supports basic data types, but arbitrary Python objects such as database models, custom classes, and sets require conversion to supported JSON values before serialization.
13. Implementing CRUD Operations
CRUD stands for Create, Read, Update, and Delete. These are the four common operations performed on resources in data-driven applications.
| Operation |
HTTP Method |
Example Endpoint |
| Create |
POST |
/api/students |
| Read all |
GET |
/api/students |
| Read one |
GET |
/api/students/1 |
| Update |
PUT or PATCH |
/api/students/1 |
| Delete |
DELETE |
/api/students/1 |
Complete Flask CRUD Example
The following learning example stores data in memory. Records disappear when the application restarts. A production system should use persistent storage, such as a database, and an appropriate data access layer.
from flask import Flask, request, jsonify, url_for
app = Flask(__name__)
students = {}
next_id = 1
@app.get("/api/students")
def get_students():
return jsonify(list(students.values()))
@app.get("/api/students/<int:student_id>")
def get_student(student_id):
student = students.get(student_id)
if student is None:
return jsonify({"error": "Student not found"}), 404
return jsonify(student)
@app.post("/api/students")
def create_student():
global next_id
if not request.is_json:
return jsonify({"error": "JSON body required"}), 415
data = request.get_json()
if not isinstance(data, dict):
return jsonify({"error": "Expected a JSON object"}), 400
name = data.get("name")
course = data.get("course")
if not isinstance(name, str) or not name.strip():
return jsonify({"error": "Name is required"}), 400
if not isinstance(course, str) or not course.strip():
return jsonify({"error": "Course is required"}), 400
student = {
"id": next_id,
"name": name.strip(),
"course": course.strip()
}
students[next_id] = student
next_id += 1
response = jsonify(student)
response.status_code = 201
response.headers["Location"] = url_for(
"get_student",
student_id=student["id"]
)
return response
@app.put("/api/students/<int:student_id>")
def update_student(student_id):
if student_id not in students:
return jsonify({"error": "Student not found"}), 404
if not request.is_json:
return jsonify({"error": "JSON body required"}), 415
data = request.get_json()
if not isinstance(data, dict):
return jsonify({"error": "Expected a JSON object"}), 400
name = data.get("name")
course = data.get("course")
if not isinstance(name, str) or not name.strip():
return jsonify({"error": "Name is required"}), 400
if not isinstance(course, str) or not course.strip():
return jsonify({"error": "Course is required"}), 400
student = {
"id": student_id,
"name": name.strip(),
"course": course.strip()
}
students[student_id] = student
return jsonify(student)
@app.patch("/api/students/<int:student_id>")
def patch_student(student_id):
if student_id not in students:
return jsonify({"error": "Student not found"}), 404
if not request.is_json:
return jsonify({"error": "JSON body required"}), 415
data = request.get_json()
if not isinstance(data, dict):
return jsonify({"error": "Expected a JSON object"}), 400
student = students[student_id]
if "name" in data:
if not isinstance(data["name"], str) or not data["name"].strip():
return jsonify({"error": "Name must be a non-empty string"}), 400
student["name"] = data["name"].strip()
if "course" in data:
if not isinstance(data["course"], str) or not data["course"].strip():
return jsonify({"error": "Course must be a non-empty string"}), 400
student["course"] = data["course"].strip()
return jsonify(student)
@app.delete("/api/students/<int:student_id>")
def delete_student(student_id):
student = students.pop(student_id, None)
if student is None:
return jsonify({"error": "Student not found"}), 404
return "", 204
if __name__ == "__main__":
app.run(debug=True)
How the CRUD API Works
- GET requests retrieve all students or one student by ID.
- POST validates the submitted JSON and creates a new student.
- PUT replaces the student's editable representation.
- PATCH changes only the supplied fields.
- DELETE removes a student and returns a 204 No Content response.
- Missing records return a 404 response.
- Invalid request bodies return an appropriate client error.
14. HTTP Status Codes for REST APIs
HTTP status codes tell clients whether a request succeeded, failed, or requires additional action.
| Status Code |
Name |
Typical Use |
| 200 |
OK |
Successful retrieval or update with a response body. |
| 201 |
Created |
A resource was successfully created. |
| 202 |
Accepted |
A request was accepted for processing, but processing may not be complete. |
| 204 |
No Content |
Successful operation with no response body. |
| 400 |
Bad Request |
Malformed or invalid request data. |
| 401 |
Unauthorized |
Valid authentication credentials are missing or unacceptable. |
| 403 |
Forbidden |
The client is not allowed to perform the requested action. |
| 404 |
Not Found |
The requested resource does not exist. |
| 405 |
Method Not Allowed |
The endpoint does not support the requested HTTP method. |
| 409 |
Conflict |
The request conflicts with the current state of a resource. |
| 415 |
Unsupported Media Type |
The request content type is not supported. |
| 422 |
Unprocessable Content |
The content type and syntax are understood, but the content fails applicable processing or validation rules. |
| 429 |
Too Many Requests |
The client exceeded a rate limit. |
| 500 |
Internal Server Error |
An unexpected server-side error occurred. |
| 503 |
Service Unavailable |
The service is temporarily unable to handle the request. |
Choose status codes consistently and document their meaning so that API consumers can handle successful responses and failures correctly.
15. Using Headers in JSON-Based Communication
HTTP headers carry metadata about requests and responses. They help the client and server determine how data should be interpreted and processed.
Important Headers
| Header |
Purpose |
Example |
| Content-Type |
Identifies the format of the message body. |
application/json |
| Accept |
Indicates which response media types the client can accept. |
application/json |
| Authorization |
Carries authentication credentials or tokens. |
Bearer token-value |
| Cache-Control |
Provides caching directives. |
no-store |
| Location |
Identifies a resource location, commonly after creation. |
/api/students/101 |
Example Using Headers with curl
curl -X POST http://127.0.0.1:5000/api/students \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{"name":"Priya","course":"Python"}'
This command submits JSON data to the API and requests a JSON response.
16. Connecting to External APIs Using Python Requests
Python's Requests library enables an application to send HTTP requests to external services. It is commonly used to retrieve API data, submit JSON payloads, and integrate third-party services.
Install Requests
python -m pip install requests
Send a GET Request
import requests
url = "https://jsonplaceholder.typicode.com/posts/1"
try:
response = requests.get(url, timeout=10)
response.raise_for_status()
data = response.json()
print(data)
except requests.exceptions.Timeout:
print("The request timed out.")
except requests.exceptions.RequestException as error:
print("API request failed:", error)
The response.json() method parses a JSON response into a Python object. The call to raise_for_status() raises an HTTP error for unsuccessful HTTP responses. A timeout prevents the request from waiting indefinitely.
Send a POST Request
import requests
url = "https://jsonplaceholder.typicode.com/posts"
payload = {
"title": "Learning Python APIs",
"body": "Understanding REST and JSON",
"userId": 1
}
try:
response = requests.post(
url,
json=payload,
timeout=10
)
response.raise_for_status()
print(response.json())
except requests.exceptions.RequestException as error:
print("Request failed:", error)
The json=payload argument serializes the Python dictionary as JSON and sets the appropriate content type. The example uses a public demonstration API; its behavior and persistence may differ from a production service.
17. Query Parameters, Path Parameters, and Request Bodies
REST APIs use different mechanisms to identify resources and provide input.
Path Parameters
Path parameters identify a particular resource or resource hierarchy.
GET /api/products/101
Here, 101 is the product identifier.
Query Parameters
Query parameters are often used for searching, sorting, filtering, and pagination.
GET /api/products?category=electronics&page=2&limit=10
In Flask, query parameters can be read through request.args.
from flask import request
@app.get("/api/products")
def list_products():
category = request.args.get("category")
page = request.args.get("page", default=1, type=int)
limit = request.args.get("limit", default=10, type=int)
return {
"category": category,
"page": page,
"limit": limit
}
A real endpoint should also validate page and limit values and apply them to a database query.
Request Body
A request body carries data submitted to an endpoint, often as JSON for create or update operations.
{
"name": "Wireless Headphones",
"price": 2499,
"category": "Electronics"
}
18. API Validation and Error Handling
API validation ensures that incoming data follows the application's rules before the server processes it. Validation should check the expected data type, required fields, acceptable ranges, and business constraints.
Example Validation Function
def validate_student(data):
if not isinstance(data, dict):
return "Expected a JSON object"
name = data.get("name")
email = data.get("email")
if not isinstance(name, str) or not name.strip():
return "Name is required"
if not isinstance(email, str) or "@" not in email:
return "A valid email is required"
return None
This is a basic educational example, not a complete email validator. Real applications should use suitable validation rules and, where appropriate, dedicated validation libraries.
Consistent JSON Error Responses
{
"error": {
"code": "VALIDATION_ERROR",
"message": "The submitted data is invalid",
"details": {
"name": "This field is required"
}
}
}
A consistent error structure helps clients display meaningful messages and handle failures predictably. Avoid returning stack traces, secret values, or internal implementation details to clients.
19. Testing REST APIs
Testing verifies that an API returns the expected status codes, response data, and error messages for valid and invalid requests.
Common API Testing Tools
- Postman: A graphical tool for creating requests, managing headers, and inspecting responses.
- curl: A command-line tool for sending HTTP requests.
- Python Requests: A library for testing endpoints programmatically.
- Flask test client: A built-in testing utility for making requests to a Flask application without running a live server.
- pytest: A testing framework commonly used for automated Python tests.
Example Using the Flask Test Client
from flask import Flask
import pytest
app = Flask(__name__)
@app.get("/api/health")
def health():
return {"status": "ok"}, 200
def test_health_endpoint():
with app.test_client() as client:
response = client.get("/api/health")
assert response.status_code == 200
assert response.json == {"status": "ok"}
Save the test in a file such as test_api.py and run it with pytest. Install pytest first if it is not available. In a larger application, keep the application and test modules organized separately.
API Testing Checklist
- Verify successful requests and expected status codes.
- Test invalid JSON and missing required fields.
- Test requests for resources that do not exist.
- Check response headers and content types.
- Verify that unauthorized users cannot access protected operations.
- Test boundary values, duplicate records, and invalid data types.
- Test timeout and external service failure handling where relevant.
20. Authentication and Authorization in REST APIs
Authentication verifies who or what is making a request. Authorization determines which resources and actions that identity is permitted to access.
Common Authentication Approaches
- API keys: Identifiers or credentials used to grant access to an API, often for service-to-service integrations.
- Token-based authentication: Clients send an access token in the Authorization header.
- OAuth 2.0: An authorization framework that allows clients to obtain limited access to resources.
- Session-based authentication: The server maintains session state associated with a client.
Bearer Token Example
GET /api/profile
Authorization: Bearer YOUR_ACCESS_TOKEN
Accept: application/json
In production, use HTTPS, protect credentials, validate tokens correctly, enforce authorization rules on the server, and avoid committing secrets to source control. The example token above is a placeholder, not a real credential.
21. REST API Security Best Practices
- Use HTTPS to protect data in transit.
- Validate and normalize all incoming data on the server.
- Apply authentication and authorization to protected endpoints.
- Never expose passwords, secret keys, or private tokens in JSON responses.
- Use parameterized database queries or a secure ORM to prevent SQL injection.
- Apply rate limits where necessary to reduce abuse.
- Set request size limits to prevent excessively large payloads.
- Return useful error messages without revealing internal details.
- Configure Cross-Origin Resource Sharing (CORS) narrowly when cross-origin browser access is needed.
- Log important events without logging sensitive credentials or unnecessary personal data.
- Use pagination for large collections and avoid returning unnecessary fields.
- Keep dependencies updated and review security advisories.
22. REST API Versioning and Documentation
API versioning helps developers evolve an API while managing compatibility for existing clients. One common approach is to include the version in the URL.
Versioned Endpoint Examples
/api/v1/students
/api/v2/students
Other versioning strategies use headers or media types. Choose a strategy that fits the application and document it consistently.
API Documentation Should Include
- Endpoint URLs and supported HTTP methods.
- Required path parameters, query parameters, and headers.
- Request body schemas and example JSON payloads.
- Response schemas and example responses.
- Success and error status codes.
- Authentication requirements and permission rules.
- Rate limits, pagination, and versioning policies.
OpenAPI is a widely used specification for describing HTTP APIs. Tools built around it can generate interactive documentation and support client development and testing.
23. Common REST API and JSON Errors
| Problem |
Possible Cause |
Solution |
| Invalid JSON |
Missing quotes, trailing commas, or malformed syntax. |
Validate the request body with a JSON parser. |
| 400 Bad Request |
Input is malformed or fails validation. |
Inspect the error response and correct the payload. |
| 401 Unauthorized |
Authentication credentials are missing or invalid. |
Provide valid credentials through the documented mechanism. |
| 403 Forbidden |
The authenticated identity lacks permission. |
Check the user's role and access policy. |
| 404 Not Found |
The route or requested resource does not exist. |
Verify the endpoint URL and resource identifier. |
| 405 Method Not Allowed |
The endpoint does not support the requested method. |
Use a supported HTTP method. |
| 415 Unsupported Media Type |
The request uses an unsupported content type. |
Send the content type required by the API. |
| 500 Internal Server Error |
An unexpected error occurred in the application. |
Inspect server logs and fix the underlying problem. |
| JSON parsing error in Python |
The response body is empty or not valid JSON. |
Check the status code, response body, and content type before parsing. |
| Request timeout |
The server or network took too long to respond. |
Configure sensible timeouts and handle retries carefully. |
24. Mini Project: Student Management REST API
Create a Student Management REST API that allows clients to add, retrieve, update, and delete student records through JSON communication.
Project Requirements
- Use Flask to build the API.
- Create endpoints for listing students and retrieving one student.
- Accept JSON data when creating a student.
- Support updating and deleting student records.
- Validate required fields and data types.
- Return appropriate HTTP status codes.
- Use consistent JSON error responses.
- Test endpoints using Postman or curl.
- Extend the project with a database for persistent storage.
Suggested Endpoint Design
| Endpoint |
Method |
Purpose |
/api/students |
GET |
Retrieve all students. |
/api/students/1 |
GET |
Retrieve student with ID 1. |
/api/students |
POST |
Create a student. |
/api/students/1 |
PUT |
Replace the student representation. |
/api/students/1 |
PATCH |
Update selected student fields. |
/api/students/1 |
DELETE |
Delete the student. |
Example POST Request
{
"name": "Neha Patil",
"email": "[email protected]",
"course": "Python Development"
}
Example Successful Response
{
"id": 1,
"name": "Neha Patil",
"email": "[email protected]",
"course": "Python Development"
}
Project Extension Ideas
- Connect the API to SQLite or PostgreSQL.
- Add filtering and pagination.
- Implement authentication and role-based authorization.
- Write automated tests for every endpoint.
- Document the API using OpenAPI.
- Deploy the application with a production WSGI server and HTTPS.
25. Practical Exercises
- JSON Fundamentals: Create a Python dictionary representing an employee and convert it to JSON using
json.dumps().
- JSON Parsing: Parse a JSON string and print selected fields.
- GET API: Build a Flask endpoint that returns a list of books.
- POST API: Create an endpoint that accepts and validates a JSON object.
- CRUD API: Implement create, read, update, and delete operations for products.
- Error Handling: Return meaningful error responses for invalid requests and missing records.
- External API Integration: Retrieve JSON from a public test API using Requests.
- API Testing: Test successful, invalid, and unauthorized requests using Postman or automated tests.
- Database Integration: Store API records in a database instead of an in-memory dictionary.
- Documentation: Document each endpoint with example requests, responses, and status codes.
26. Interview Questions and Answers
Q1. What is an API?
Answer: An API is an interface that allows software components or applications to communicate through defined operations, inputs, and outputs.
Q2. What is a REST API?
Answer: A REST API is an API designed around REST architectural principles, typically using HTTP methods and resource-oriented URLs to interact with resources.
Q3. What is JSON?
Answer: JSON is a lightweight text-based data interchange format that supports objects, arrays, strings, numbers, booleans, and null values.
Q4. What is the difference between JSON and a Python dictionary?
Answer: A Python dictionary is an in-memory Python data structure, while JSON is a text-based data format. Python dictionaries can be serialized to JSON when their values are compatible with JSON types.
Q5. What is the difference between GET and POST?
Answer: GET is generally used to retrieve resources, whereas POST submits data for processing and is commonly used to create resources.
Q6. What is the difference between PUT and PATCH?
Answer: PUT generally replaces a resource representation, while PATCH applies partial modifications.
Q7. What is serialization?
Answer: Serialization converts an in-memory object into a format suitable for storage or transfer, such as converting a Python dictionary into JSON text.
Q8. What does Flask's jsonify() function do?
Answer: It creates an HTTP response containing JSON data and sets the response media type to application/json.
Q9. What is the purpose of the Content-Type header?
Answer: It identifies the media type of the request or response body, such as application/json.
Q10. What is the purpose of HTTP status codes?
Answer: Status codes indicate the outcome of an HTTP request, including success, client errors, and server errors.
Q11. What is the difference between 401 and 403?
Answer: A 401 response indicates that valid authentication credentials are missing or unacceptable. A 403 response indicates that the server refuses the requested operation, commonly because the client lacks permission.
Q12. How do you consume an API in Python?
Answer: Use an HTTP client such as Requests to send a request, inspect the response status, handle errors, and parse the JSON body using response.json().
Q13. Why is request validation important?
Answer: Validation ensures that incoming data has the expected structure and values before it is processed or stored.
Q14. What is stateless communication in REST?
Answer: Each request contains the information required to process it. The server does not depend on stored client session state to understand the request.
Q15. How can you secure a REST API?
Answer: Use HTTPS, appropriate authentication and authorization, input validation, rate limiting, secure database queries, careful error handling, and protected secret management.
27. Quick Revision Checklist
- API stands for Application Programming Interface.
- REST is an architectural style for networked applications.
- JSON is a common format for exchanging structured data.
- GET retrieves data; POST commonly creates resources.
- PUT generally replaces a resource; PATCH applies partial updates.
- DELETE removes a resource.
- Python's
json module supports JSON serialization and parsing.
- Flask provides routing, request handling, and JSON responses.
- Requests allows Python applications to call external APIs.
- Use meaningful status codes and consistent error responses.
- Validate incoming JSON before processing it.
- Use HTTPS and enforce authentication and authorization where required.
- Test API endpoints using automated tests, Postman, or curl.
- Use persistent storage for production data instead of an in-memory collection.
28. Conclusion
Building REST APIs and understanding JSON-based communication are essential skills for Python developers who work on web applications, backend systems, mobile applications, and service integrations.
REST APIs provide a structured way to expose application resources through HTTP endpoints, while JSON offers a lightweight format for exchanging data between clients and servers. With Flask, developers can create API routes, process incoming JSON, implement CRUD operations, validate requests, return appropriate status codes, and integrate external services using Python Requests.
Consistent API design, thorough testing, input validation, secure authentication, and clear documentation help make APIs reliable and maintainable.
Continue learning through the Python Training Course at JustAcademy. Visit the JustAcademy Official Website or register for a course demo to explore further learning opportunities.